package com.computaris.ws;

import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;


import org.hibernate.FlushMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.context.ManagedSessionContext;

import com.computaris.entities.Subscriber;
import com.computaris.entities.SubscriberDetails;
import com.computaris.entities.Subscription;

@WebService(endpointInterface = "com.computaris.ws.PostpayBillingWs",targetNamespace="http://ws.postpay.computaris.com")
public class PostpayBillingWsImpl implements PostpayBillingWs {


	@WebMethod
	public ResultCode createSubscriber(@WebParam(name="IMSI") String imsi, 
			@WebParam(name="MSISDN") String msisdn, 
			@WebParam(name="Status") int status,  
			@WebParam(name="SubscriptionName") String subscriptionName) {

		ResultCode res = new ResultCode();
		res.setStatus(1);

		// try to create the subscriber
		Session session = createNewSessionAndTransaction();

		//check if msisdn or imsi already exists in db
		Query qr = session.createQuery("from Subscriber where status = 0 and (msisdn = :msisdn or imsi = :imsi)")
				.setParameter("msisdn", msisdn).setParameter("imsi",imsi);
		try{
			List subs = qr.list();
			
			/*if( subs.size() > 0){
				res.setDescription("Subscriber with msisdn: " + msisdn +" or imsi= " + imsi + " already exists.");
				return res;
			}*/
		}catch(Exception e){
			rollbackTransaction(session);
			res.setDescription(e.getMessage());
			return res;
		}

		// try to get subscription
		Subscription subscription = null;
		Query query = session.createQuery("from Subscription where name = :name").setParameter("name", subscriptionName);
		try{    		
			List list = query.list();
			if(list != null && list.size() > 0 ){
				subscription = (Subscription) list.get(0);
			}
			else {
				res.setDescription("Subscription: " + subscriptionName + " is not defined in DB.");
				return res;
			}
		}catch(Exception e){
			rollbackTransaction(session);
			res.setDescription(e.getMessage()); 
			return res;
		}
		
		Subscriber sub = new Subscriber();
		sub.setImsi(imsi);
		
		// truncate msisdn if it's lenght is more than 20
		if(msisdn.length()>20){
			msisdn = msisdn.substring(0, 20);
		}
		
		sub.setMsisdn(msisdn);
		sub.setStatus(status);
		sub.setSubscriptionId(subscription.getId());

		Date now = GregorianCalendar.getInstance().getTime();
		sub.setUpdateDate(now);
		try{
			session.save(sub);
		}
		catch(Exception e){
			rollbackTransaction(session);
			res.setDescription(e.getMessage());
			return res;
		}
		
		commitTransaction(session);
		res.setStatus(0);
		res.setDescription("SUCCESS");

		return res;
	}

	@WebMethod
	public ResultCode deactivateSubscriber(@WebParam(name="MSISDN") String msisdn){
		ResultCode res = new ResultCode();
//		res.setStatus(1);
		res.setStatus(0);

		Session session = createNewSessionAndTransaction();

		Query query = session.createQuery("from Subscriber where msisdn = :msisdn ")
				.setParameter("msisdn", msisdn);

		// try to find subscriber
		Subscriber subscriber = null;
		try{
			List list = query.list();
			if(list != null && list.size() > 0 ){
				subscriber = (Subscriber) list.get(0);
			}
			else {
				res.setDescription("Subscriber with msisdn: " + msisdn + " is not defined in DB.");
				return res;
			}
		}catch(Exception e){
			res.setDescription(e.getMessage());
			return res;    		
		}

		// set update datetime
		/*Date now = GregorianCalendar.getInstance().getTime();
		subscriber.setUpdateDate(now);*/
		subscriber.setStatus(1);

		commitTransaction(session);

		res.setStatus(0);
		res.setDescription("SUCCESS");

		return res;
	}

	@WebMethod
	public SubscriberDetails getSubscriberDetails(@WebParam(name="MSISDN") String msisdn){

		SubscriberDetails sd = new SubscriberDetails();
		sd.setStatus(1);

		Session session = createNewSessionAndTransaction();

		Query query = session.createQuery("from Subscriber where msisdn = :msisdn ")
				.setParameter("msisdn", msisdn);

		// try to find subscriber
		Subscriber subscriber = null;
		try{
			List list = query.list();
			if(list != null && list.size() > 0 ){
				sd.setStatus(0);
				subscriber = (Subscriber) list.get(0);
				sd.setSubscriberDetails(subscriber);
			}
			else {
				sd.setStatus(1);
				sd.setDescription("Subscriber with msisdn: " + msisdn + " is not defined in DB.");    			
			}
		}catch(Exception e){
			sd.setDescription(e.getMessage());
			rollbackTransaction(session);
			return sd;
		}

		commitTransaction(session);
		return sd;
	} 


	protected org.hibernate.Session createNewSession() {
		org.hibernate.classic.Session session = SessionFactoryHelper.getSessionFactory().openSession();
		session.setFlushMode(FlushMode.MANUAL);
		ManagedSessionContext.bind(session);
		return (org.hibernate.Session) session;
	}

	/**
	 * Start a new Transaction in the given session
	 * @param session The session to create the transaction in
	 */
	protected void startNewTransaction(Session session) {
		session.beginTransaction();
	}

	/**
	 * Shortcut method that creates a new session and begins a transaction in it
	 * @return A new session with a transaction started
	 */
	protected org.hibernate.Session createNewSessionAndTransaction() {
		Session session = createNewSession();
		startNewTransaction(session);
		return session;
	}
	/**
	 * Commit the transaction within the given session. This method unbinds
	 * the session from the session context (ManagedSessionContext), flushes
	 * the session, commmits the session and then closes the session
	 * @param session The session with the transaction to commit
	 */
	protected void commitTransaction(Session session) {
		ManagedSessionContext.unbind(SessionFactoryHelper.getSessionFactory());
		session.flush();
		session.getTransaction().commit();
		session.close();
	}
	
	protected void rollbackTransaction(Session session) {
		ManagedSessionContext.unbind(SessionFactoryHelper.getSessionFactory());
		session.getTransaction().rollback();
		session.close();
	}

}

